interface EventListener {
    name: string;
    handler: (...args: any)=>void;
    context?: any;
}

export default class BaseClass {
    private events: Array<string>;
    private eventListeners: Array<EventListener>;
    constructor (events: Array<string>){
        this.events = events;
        this.eventListeners = [];
    }

    public on<T extends BaseClass>(name: string, handler: (...args: any)=>void, context?: T){
        if(!this.events.includes(name)){
            throw new Error(`Event ${name} is not defined`);
        }
        this.eventListeners.push({ name, handler, context });
    }

    public emit(name: string, ...args: any){
        if(!this.events.includes(name)){
            throw new Error(`Event ${name} is not defined`);
        }
        this.eventListeners.forEach((listener)=>{
            if(listener.name === name){
                listener.handler.apply(listener.context || this, args);
            }
        });
    }

    public off(name: string){
        if(!this.events.includes(name)){
            throw new Error(`Event ${name} is not defined`);
        }
        this.eventListeners = this.eventListeners.filter((listener)=>{
            return listener.name !== name;
        });
    }

    public destroy(){
        this.eventListeners = [];
    }

    public dispose(){
        this.destroy();
    }
}